package com.docmgmt.mvp.controller;

import com.docmgmt.mvp.dto.*;
import com.docmgmt.mvp.exception.UnauthorizedException;
import com.docmgmt.mvp.service.TagService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * Tag Management Controller
 *
 * @author Dora
 */
@Slf4j
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class TagController {

    private final TagService tagService;

    /**
     * 4.5.1 Create Tag
     *
     * POST /api/v1/tags
     */
    @PostMapping("/tags")
    public Result<TagVO> createTag(@Valid @RequestBody CreateTagRequest request) {
        Long userId = getCurrentUserId();

        log.info("POST /api/v1/tags - userId={}, name={}", userId, request.getName());

        TagVO tag = tagService.createTag(request.getName(), request.getColor(), userId);
        return Result.success("Tag created successfully", tag);
    }

    /**
     * 4.5.2 Delete Tag
     *
     * DELETE /api/v1/tags/{id}
     */
    @DeleteMapping("/tags/{tagId}")
    public Result<Void> deleteTag(@PathVariable Long tagId) {
        Long userId = getCurrentUserId();

        log.info("DELETE /api/v1/tags/{} - userId={}", tagId, userId);

        tagService.deleteTag(tagId, userId);
        return Result.success("Tag deleted successfully");
    }

    /**
     * 4.5.3 List User Tags
     *
     * GET /api/v1/tags/my
     */
    @GetMapping("/tags/my")
    public Result<List<TagVO>> listMyTags() {
        Long userId = getCurrentUserId();

        log.info("GET /api/v1/tags/my - userId={}", userId);

        List<TagVO> tags = tagService.listUserTags(userId);
        return Result.success("Query successful", tags);
    }

    /**
     * 4.5.4 Add Tag to File
     *
     * POST /api/v1/files/{id}/tags
     */
    @PostMapping("/files/{fileId}/tags")
    public Result<List<TagVO>> addFileTags(
            @PathVariable Long fileId,
            @Valid @RequestBody AddFileTagRequest request) {
        Long userId = getCurrentUserId();

        log.info("POST /api/v1/files/{}/tags - userId={}, tagIds={}",
                fileId, userId, request.getTagIds());

        List<TagVO> tags = tagService.addFileTag(fileId, request.getTagIds(), userId);
        return Result.success("Tags added successfully", tags);
    }

    /**
     * 4.5.5 Remove Tag from File
     *
     * DELETE /api/v1/files/{fileId}/tags/{tagId}
     */
    @DeleteMapping("/files/{fileId}/tags/{tagId}")
    public Result<Void> removeFileTag(
            @PathVariable Long fileId,
            @PathVariable Long tagId) {
        Long userId = getCurrentUserId();

        log.info("DELETE /api/v1/files/{}/tags/{} - userId={}", fileId, tagId, userId);

        tagService.removeFileTag(fileId, tagId, userId);
        return Result.success("Tag removed successfully");
    }

    /**
     * 4.5.6 List File Tags
     *
     * GET /api/v1/files/{id}/tags
     */
    @GetMapping("/files/{fileId}/tags")
    public Result<List<TagVO>> listFileTags(@PathVariable Long fileId) {
        log.info("GET /api/v1/files/{}/tags", fileId);

        List<TagVO> tags = tagService.listFileTags(fileId);
        return Result.success("Query successful", tags);
    }

    /**
     * 4.5.7 List Files by Tag
     *
     * GET /api/v1/tags/{id}/files
     */
    @GetMapping("/tags/{tagId}/files")
    public Result<List<FileVO>> listFilesByTag(@PathVariable Long tagId) {
        Long userId = getCurrentUserId();

        log.info("GET /api/v1/tags/{}/files - userId={}", tagId, userId);

        List<FileVO> files = tagService.listFilesByTag(tagId, userId);
        return Result.success("Query successful", files);
    }

    /**
     * Get current user ID from Spring Security context
     */
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new UnauthorizedException("Not logged in or authentication expired");
        }

        Object principal = authentication.getPrincipal();
        if (principal instanceof Long) {
            return (Long) principal;
        }

        throw new UnauthorizedException("Invalid authentication information");
    }
}
